using System;
using JetBrains.ReSharper.Psi.Parsing;
using JetBrains.ReSharper.Plugins.Json.Psi.Parsing.TokenNodeTypes;
using JetBrains.Text;
using JetBrains.Util;

%%

%unicode

%init{
  currentTokenType = null;
%init}

%namespace JetBrains.ReSharper.Plugins.Json.Psi.Parsing
%class JsonNewLexerGenerated
%implements IIncrementalLexer
%function _locateToken
%virtual
%public
%type TokenNodeType
%ignorecase

%eofval{
  currentTokenType = null; return currentTokenType;
%eofval}

%include Chars.lex

CARRIAGE_RETURN_CHAR=\u000D
LINE_FEED_CHAR=\u000A
NEW_LINE_PAIR=({CARRIAGE_RETURN_CHAR}?{LINE_FEED_CHAR}|{CARRIAGE_RETURN_CHAR}|(\u0085)|(\u2028)|(\u2029))
NOT_NEW_LINE=([^\u0085\u2028\u2029\u000D\u000A])

ASTERISKS="*"+
INPUT_CHARACTER={NOT_NEW_LINE}

SINGLE_LINE_COMMENT=("//"{INPUT_CHARACTER}*)

DELIMITED_COMMENT_SECTION=([^\*\uE000\uE001]|({ASTERISKS}[^\*\/\uE000\uE001]))
UNFINISHED_DELIMITED_COMMENT="/*"{DELIMITED_COMMENT_SECTION}*
DELIMITED_COMMENT={UNFINISHED_DELIMITED_COMMENT}{ASTERISKS}"/"

LINE_CONTINUATOR=(\\{NEW_LINE_PAIR})
SIMPLE_ESCAPE_SEQUENCE=(\\[^\u0085\u2028\u2029\u000D\u000A])
HEXADECIMAL_ESCAPE_SEQUENCE=(\\x{HEX_DIGIT}({HEX_DIGIT}|{HEX_DIGIT}{HEX_DIGIT}|{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT})?)
UNICODE_ESCAPE_SEQUENCE=((\\u{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT})|(\\U{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT}))

WHITE_SPACE_CHAR=({UNICODE_ZS}|(\u0009)|(\u000B)|(\u000C)|(\u200B)|(\uFEFF))
WHITE_SPACE=({WHITE_SPACE_CHAR}+)

DECIMAL_DIGIT=[0-9]
OCTAL_DIGIT=[0-7]
BINARY_DIGIT=(0|1)
HEX_DIGIT=({DECIMAL_DIGIT}|[A-Fa-f])

NUMERIC_LITERAL_SEPARATOR="_"

DECIMAL_DIGITS=({DECIMAL_DIGIT}+({NUMERIC_LITERAL_SEPARATOR}{DECIMAL_DIGIT}+)*)
HEXADECIMAL_DIGITS=({HEX_DIGIT}+({NUMERIC_LITERAL_SEPARATOR}{HEX_DIGIT}+)*)
OCTAL_DIGITS=({OCTAL_DIGIT}+({NUMERIC_LITERAL_SEPARATOR}{OCTAL_DIGIT}+)*)
BINARY_DIGITS=({BINARY_DIGIT}+({NUMERIC_LITERAL_SEPARATOR}{BINARY_DIGIT}+)*)

DECIMAL_INTEGER_LITERAL=({DECIMAL_DIGITS})
HEXADECIMAL_INTEGER_LITERAL=(0[Xx]({HEXADECIMAL_DIGITS}))
OCTAL_INTEGER_LITERAL=(0[Oo]({OCTAL_DIGITS}))
BINARY_INTEGER_LITERAL=(0[Bb]({BINARY_DIGITS}))
INTEGER_LITERAL=({DECIMAL_INTEGER_LITERAL}|{HEXADECIMAL_INTEGER_LITERAL}|{OCTAL_INTEGER_LITERAL}|{BINARY_INTEGER_LITERAL})

EXPONENT_PART=([eE]([+-])?{DECIMAL_DIGITS})
REAL_LITERAL=(((({DECIMAL_DIGITS})?"."{DECIMAL_DIGITS})|({DECIMAL_DIGITS}"."({DECIMAL_DIGITS})?))({EXPONENT_PART})?)|({DECIMAL_DIGITS}{EXPONENT_PART})

NUMERIC_LITERAL=({INTEGER_LITERAL}|{REAL_LITERAL})

DOUBLE_STRING_LITERAL_CHARACTER_INNER=[^\"\\\u0085\u2028\u2029\u000D\u000A\uE000]
SINGLE_STRING_LITERAL_CHARACTER_INNER=[^\'\\\u0085\u2028\u2029\u000D\u000A\uE000]

DOUBLE_STRING_LITERAL_CHARACTER=({DOUBLE_STRING_LITERAL_CHARACTER_INNER}|{HEXADECIMAL_ESCAPE_SEQUENCE}|{UNICODE_ESCAPE_SEQUENCE}|{SIMPLE_ESCAPE_SEQUENCE}|{LINE_CONTINUATOR})
SINGLE_STRING_LITERAL_CHARACTER=({SINGLE_STRING_LITERAL_CHARACTER_INNER}|{HEXADECIMAL_ESCAPE_SEQUENCE}|{UNICODE_ESCAPE_SEQUENCE}|{SIMPLE_ESCAPE_SEQUENCE}|{LINE_CONTINUATOR})


DOUBLE_QUOTED_STRING=(\"{DOUBLE_STRING_LITERAL_CHARACTER}*\")
SINGLE_QUOTED_STRING=(\'{SINGLE_STRING_LITERAL_CHARACTER}*\')

LETTER_CHARACTER=({UNICODE_LL}|{UNICODE_LM}|{UNICODE_LO}|{UNICODE_LT}|{UNICODE_LU}|{UNICODE_NL}|{UNICODE_ESCAPE_SEQUENCE})
DECIMAL_DIGIT_CHARACTER={UNICODE_ND}
CONNECTING_CHARACTER={UNICODE_PC}
COMBINING_CHARACTER=({UNICODE_MC}|{UNICODE_MN})

IDENTIFIER_START_CHARACTER=({LETTER_CHARACTER}|([$_]))
IDENTIFIER_PART_CHARACTER=({LETTER_CHARACTER}|{DECIMAL_DIGIT_CHARACTER}|{CONNECTING_CHARACTER}|{COMBINING_CHARACTER}|([$_]))
IDENTIFIER=({IDENTIFIER_START_CHARACTER}({IDENTIFIER_PART_CHARACTER}*))

%%
<YYINITIAL> {WHITE_SPACE}  { return JsonNewTokenNodeTypes.WHITE_SPACE; }
<YYINITIAL> {NEW_LINE_PAIR}  { return JsonNewTokenNodeTypes.NEW_LINE; }
<YYINITIAL> "{"  { return JsonNewTokenNodeTypes.LBRACE; }
<YYINITIAL> "}" { return JsonNewTokenNodeTypes.RBRACE; }
<YYINITIAL> "["  { return JsonNewTokenNodeTypes.LBRACKET; }
<YYINITIAL> "]"  { return JsonNewTokenNodeTypes.RBRACKET; }
<YYINITIAL> "," { return JsonNewTokenNodeTypes.COMMA; }
<YYINITIAL> ":"  { return JsonNewTokenNodeTypes.COLON; }
<YYINITIAL> "true"  { return JsonNewTokenNodeTypes.TRUE_KEYWORD; }
<YYINITIAL> "false"  { return JsonNewTokenNodeTypes.FALSE_KEYWORD; }
<YYINITIAL> "null"  { return JsonNewTokenNodeTypes.NULL_KEYWORD; }

<YYINITIAL> {SINGLE_LINE_COMMENT}  { return JsonNewTokenNodeTypes.SINGLE_LINE_COMMENT; }
<YYINITIAL> {DELIMITED_COMMENT}  { return JsonNewTokenNodeTypes.DELIMITED_COMMENT; }
<YYINITIAL> {NUMERIC_LITERAL}  { return JsonNewTokenNodeTypes.NUMERIC_LITERAL; }
<YYINITIAL> {IDENTIFIER}  { return JsonNewTokenNodeTypes.IDENTIFIER; }
<YYINITIAL> {SINGLE_QUOTED_STRING}  { return JsonNewTokenNodeTypes.SINGLE_QUOTED_STRING; }
<YYINITIAL> {DOUBLE_QUOTED_STRING}  { return JsonNewTokenNodeTypes.DOUBLE_QUOTED_STRING; }

<YYINITIAL> . { return JsonNewTokenNodeTypes.EOF; }
